package com.unitd.frame.mybatis.plugin.rw;

import com.unitd.frame.mybatis.interceptor.IInterceptorHandler;
import com.unitd.frame.mybatis.datasource.DataSourceContextHolder;
import com.unitd.frame.mybatis.plugin.MybatisPluginInterceptor;
import org.apache.ibatis.executor.keygen.SelectKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Invocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @desc 读写分离自动路由拦截处理, 实现Mybatis插件的拦截处理器接口
 * @filename RwRouteHandler.java
 * @copyright www.unitd.com
 * @author Hudan
 * @version 1.0
 * @date 2017/2/18
 */
public class RwRouteHandler implements IInterceptorHandler {

	private static final Logger logger = LoggerFactory.getLogger(RwRouteHandler.class);

	/**
	 * @param context Mybatis上下文
	 * @desc 进入拦截器, 开始进行拦截处理
	 */
	@Override
	public void start(MybatisPluginInterceptor context) {
	}

	/**
	 * @return int
	 * @desc 设置不同拦截器的加载顺序
	 */
	@Override
	public int interceptorOrder() {
		return 1;
	}

	/**
	 * @param invocation 调用器
	 * @desc 拦截器开启调用拦截处理
	 */
	@Override
	public Object onInterceptor(Invocation invocation) throws Throwable {

		Object[] objects = invocation.getArgs();
		MappedStatement ms = (MappedStatement) objects[0];
		// 已指定强制使用
		if (DataSourceContextHolder.get().isForceUseMaster()) {
			logger.debug("Method[{}] force use Master..", ms.getId());
			return null;
		}

		// 读方法
		if (ms.getSqlCommandType().equals(SqlCommandType.SELECT)) {
			// !selectKey 为自增id查询主键(SELECT LAST_INSERT_ID() )方法，使用主库
			if (!ms.getId().contains(SelectKeyGenerator.SELECT_KEY_SUFFIX)) {
				DataSourceContextHolder.get().useSlave(true);
				logger.debug("Method[{} use Slave Strategy..", ms.getId());
			}
		} else {
			logger.debug("Method[{}] use Master Strategy..", ms.getId());
			DataSourceContextHolder.get().useSlave(false);
		}
		return null;
	}

	/**
	 * @param invocation 调用器
	 * @param result     结果对象
	 * @desc 结束拦截调用处理
	 */
	@Override
	public void onFinished(Invocation invocation, Object result) {
	}

	/**
	 * @desc 关闭拦截器, 退出拦截
	 */
	@Override
	public void close() {
	}
}